#pragma once
namespace graph_virtual
{
   namespace details
   {

   }
   inline virtual_view_vertex_iterator_t::virtual_view_vertex_iterator_t(virtual_graph_view_ptr_t view)
      :  view_(view)
      ,  it_(vertices(view->get_graph_ptr()))
   {
       if (!it_.is_empty() && !view_->vertex_predicate(*it_))
       {
           ++(*this);
       }
   }
   inline void virtual_view_vertex_iterator_t::operator ++ ()
   {
       ++it_;
       for(;!it_.is_empty() && !view_->vertex_predicate(*it_); ++it_);
   }

   inline graph_basic::vertex_t& virtual_view_vertex_iterator_t::operator * ()
   {
      return *it_;
   }
   inline graph_basic::vertex_t const & virtual_view_vertex_iterator_t::operator * () const
   {
      return *it_;
   }
   inline bool virtual_view_vertex_iterator_t::is_empty() const
   {
       return it_.is_empty();
   }
   
   inline virtual_view_edge_iterator_t::virtual_view_edge_iterator_t(virtual_graph_view_ptr_t view)
      :   edge_it_( edges(view->get_graph_ptr()))
      ,   view_(view)
{
    if (!edge_it_.is_empty() && !view_->edge_predicate(*edge_it_))
    {
        ++(*this);
    }

}
   inline bool virtual_view_edge_iterator_t::is_empty() const
   {
       return edge_it_.is_empty();
   }
   inline void virtual_view_edge_iterator_t::operator ++ ()
   {
       ++edge_it_;
       while( !edge_it_.is_empty() && !view_->edge_predicate(*edge_it_) )
       {
           ++edge_it_;
       }
   }

   inline graph_basic::edge_t virtual_view_edge_iterator_t::operator * ()
   {
       return *edge_it_;
   }
   inline graph_basic::edge_t const virtual_view_edge_iterator_t::operator * () const
   {
       return *edge_it_;
   }


   inline virtual_view_adjacent_edges_iterator_t::virtual_view_adjacent_edges_iterator_t(graph_basic::vertex_id_t source_v_id, virtual_graph_view_ptr_t view)
      :  view_(view)
      ,  it_(adjacent_edges(source_v_id, view->get_graph_ptr()))
   {
       for(;!it_.is_empty() && !view_->edge_predicate(*it_); ++it_);
   }
   inline void virtual_view_adjacent_edges_iterator_t::operator ++ ()
   {
       ++it_;
       while(!it_.is_empty() && !view_->edge_predicate(*it_))
       {
           ++it_;
       }
   }
   inline graph_basic::edge_t virtual_view_adjacent_edges_iterator_t::operator * ()
   {
       return *it_;
   }
   inline graph_basic::edge_t const virtual_view_adjacent_edges_iterator_t::operator * () const
   {
       return *it_;
   }
   inline bool virtual_view_adjacent_edges_iterator_t::is_empty() const
   {
       return it_.is_empty();
   }
   
   inline virtual_view_adjacent_vertices_iterator_t::virtual_view_adjacent_vertices_iterator_t(virtual_view_adjacent_edges_iterator_t it)
      :  it_(it)
   {}
   inline void virtual_view_adjacent_vertices_iterator_t::operator++()
   {
       ++it_;
   }
   inline graph_basic::vertex_t& virtual_view_adjacent_vertices_iterator_t::operator * ()
   {
       return it_.view_->get_vertex_by_id((*it_).get_target_vertex_id());
   }
   inline graph_basic::vertex_t const & virtual_view_adjacent_vertices_iterator_t::operator * () const
   {
      return it_.view_->get_vertex_by_id((*it_).get_target_vertex_id());
   }
   inline bool virtual_view_adjacent_vertices_iterator_t::is_empty() const
   {
       return it_.is_empty();
   }
   inline virtual_view_vertex_iterator_t vertices(virtual_graph_view_ptr_t view)
   {
       return virtual_view_vertex_iterator_t(view);
   }

   inline virtual_view_edge_iterator_t edges(virtual_graph_view_ptr_t view)
   {
       return virtual_view_edge_iterator_t(view);
   }

   inline virtual_view_adjacent_edges_iterator_t adjacent_edges(graph_basic::vertex_id_t souce_v_id, virtual_graph_view_ptr_t view)
   {
       return virtual_view_adjacent_edges_iterator_t(souce_v_id, view);
   }
   inline virtual_view_adjacent_vertices_iterator_t adjacent_vertices(graph_basic::vertex_id_t souce_v_id, virtual_graph_view_ptr_t view)
   {
       return virtual_view_adjacent_vertices_iterator_t(
                  adjacent_edges(souce_v_id, view)
              );
   }
}